HIFORMAT: 1A

# OpenGrok

OpenGrok RESTful API documentation. The following endpoints are accessible under `/api/v1` with the exception of `/metrics`.

Besides `/suggester`, `/search`, `/system/ping` and `/metrics` endpoints, everything is accessible from `localhost` only
unless authentication bearer tokens are configured in the web application and used via the 'Authorization' HTTP header
(within HTTPS connection).

Some of the APIs are asynchronous. They return status code 202 (Accepted) and a Location header that contains the URL
for the status endpoint to check for the result of the API call. Once the status API returns result other than 202,
the client should issue DELETE request to this URL to clean up server resources.

For all entry points that modify web application configuration it is worth noting that
the configuration has to be retrieved and stored on disk (using the configuration specific
entry points) in order to be persistent (e.g. in case of application server restart or
web application redeploy).

## Annotation [/annotation{?path}]

### Get annotation for a file [GET]

+ Parameters
  + path (string) - path of file, relative to source root

+ Response 200 (application/json)
  + Body

            [
              {
                "revision": "c55d5891",
                "author": "Adam Hornáček",
                "description": "changeset: c55d5891\nsummary: Rewrite README.txt to use markdown syntax\nuser: Adam Hornáček <adam.hornacek@oracle.com>\ndate: Wed Aug 30 17:42:12 CEST 2017",
                "version": "1/15"
              },
              {
                "revision": "5e0c6b22",
                "author": "Vladimir Kotal",
                "description": "changeset: 5e0c6b22\nsummary: bump year\nuser: Vladimir Kotal <vlada@devnull.cz>\ndate: Thu Jul 18 14:43:01 CEST 2019",
                "version": "14/15"
              }
            ]

## Authorization framework reload [/configuration/authorization/reload]

### reloads authorization framework [POST]

This is asynchronous API endpoint.

+ Request (application/text)

+ Response 204

## Configuration [/configuration]

### return XML representation of configuration [GET]

+ Response 200 (application/xml)
  + Body

        ```
        <?xml version="1.0" encoding="UTF-8"?>
        <java version="1.8.0_172" class="java.beans.XMLDecoder">
         <object class="org.opengrok.indexer.configuration.Configuration" id="Configuration0">
          <void property="allowLeadingWildcard">
           <boolean>true</boolean>
          </void>
         </object>
        </java>
        ```

### sets configuration from XML representation [PUT]

This is asynchronous API endpoint.

+ Request (application/xml)
  + Body

        ```
        <?xml version="1.0" encoding="UTF-8"?>
        <java version="1.8.0_172" class="java.beans.XMLDecoder">
         <object class="org.opengrok.indexer.configuration.Configuration" id="Configuration0">
          <void property="allowLeadingWildcard">
           <boolean>true</boolean>
          </void>
         </object>
        </java>
        ```

+ Response 201 (application/json)

## Configuration field [/configuration/{field}{?reindex}]

### returns specific configuration field [GET]

+ Response 200 (application/json)

### sets specific configuration field [PUT]

This is asynchronous API endpoint.

+ Parameters
  + reindex (boolean) - specifies if the underlying data were also reindexed (refreshes some searchers and additional data structures)

+ Request (application/text)

        string value of the field to set

+ Response 204

## File content [/file/content{?path}]

### get file content [GET]

Honors the `Accept` header. If the value of the header is set to `text/plain`
and there is a document in the index that has the genre detected as plain text,
the contents of the document will be returned. If the document is not found,
HTTP error 404 will be returned. If the genre of the document is not plain text,
HTTP error 406 will be returned.
Alternatively, one can use the `application/octet-stream` value of the header
which bypasses the document and genre check.
The `Content-type` header of the reply will be set accordingly.

+ Parameters
  + path (string) - path of file, relative to source root

+ Response 200 (text/plain)
  + Body

            foo
            bar

+ Response 200

## File genre [/file/genre{?path}]

### get file genre [GET]

+ Parameters
  + path (string) - path of file, relative to source root

+ Response 200 (text/plain)
  + Body

            genre as identified by analyzer, could be PLAIN, XREFABLE, IMAGE, DATA, HTML

## File definitions [/file/defs{?path}]

### get file definitions [GET]

+ Parameters
  + path (string) - path of file, relative to source root

+ Response 200 (application/json)
  + Body

            [
              {
                "type": "function",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,",
                "symbol": "AES_cbc_encrypt",
                "lineStart": 5,
                "lineEnd": 20,
                "line": 20,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "in",
                "lineStart": 21,
                "lineEnd": 44,
                "line": 20,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "out",
                "lineStart": 46,
                "lineEnd": 64,
                "line": 20,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "len",
                "lineStart": 21,
                "lineEnd": 31,
                "line": 21,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "key",
                "lineStart": 33,
                "lineEnd": 51,
                "line": 21,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "ivec",
                "lineStart": 21,
                "lineEnd": 40,
                "line": 22,
                "namespace": null
              },
              {
                "type": "argument",
                "signature": "(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "text": "AES_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const AES_KEY * key,unsigned char * ivec,const int enc)",
                "symbol": "enc",
                "lineStart": 42,
                "lineEnd": 55,
                "line": 22,
                "namespace": null
              }
            ]


## History [/history{?path,withFiles,start,max}]

### get history entries [GET]

+ Parameters
  + path (string) - path of file/directory to get history for, relative to source root
  + withFiles (optional, boolean) - whether to include list of files
  + start (optional, int) - start index
  + max (optional, int) - number of entries to get (default value 1000)

+ Response 200 (application/json)
  + Body

            {
              "entries": [
                {
                  "revision": "86b0ab6b",
                  "date": 1565163646000,
                  "author": "Adam Hornacek <adam.hornacek@oracle.com>",
                  "tags": null,
                  "message": "Try to use mvnw in CI",
                  "files": [
                    "/opengrok/docker/README.md"
                  ]
                },
                {
                  "revision": "a391bead",
                  "date": 1564745178000,
                  "author": "Adam Hornacek <adam.hornacek@oracle.com>",
                  "tags": null,
                  "message": "Fix docker readme typo",
                  "files": [
                    "/opengrok/docker/README.md"
                  ]
                },
                {
                  "revision": "33551f14",
                  "date": 1563531391000,
                  "author": "Vladimir Kotal <vlada@devnull.cz>",
                  "tags": "1.3.0, 1.2.25, 1.2.24",
                  "message": "document docker-compose",
                  "files": [
                    "/opengrok/docker/README.md"
                  ]
                }
              ],
              "start": 5,
              "count": 3,
              "total": 24
            }



## Directory listing [/list{?path}]

### get directory entries [GET]

+ Parameters
  + path (string) - path of file/directory to get listing for, relative to source root, starting with /

+ Response 200 (application/json)
  + Body

            [
              {
                "path": "/lucene/.github",
                "numLines": 178,
                "loc": 125,
                "date": 1673456294670,
                "description": null,
                "pathDescription": "",
                "isDirectory": true,
                "size": null
              },
              {
                "path": "/lucene/.asf.yaml",
                "numLines": 25,
                "loc": 21,
                "date": 1673456294670,
                "description": null,
                "pathDescription": "",
                "isDirectory": false,
                "size": 574
              }
            ]


## Include files reload [/system/includes/reload]

### reloads all include files for web application [PUT]

+ Response 204

## Get last index time [/system/indextime]

The time is in the ISO 8601 format in UTC time zone.

### Retrieve last index time [GET]

+ Response 200 (application/json)
  + Body

            "2021-02-15T16:39:16.409+00:00"

## Messages [/messages{?tag}]

### adds message to a system [POST]

Usable values for `messageLevel` are: `success`, `info`, `warning`, `error`.
This will affect CSS class of the displayed message, leading to different coloring.

The values in the `tags` list can be: `main` (special value for top level message in the whole web application),
project name and project group name.

The format of `duration` is the same as Java's java.time.Duration class,
see https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-

+ Request (application/json)

        {
          "tags": ["main"],
          "messageLevel": "info",
          "text":"test message",
          "duration":"PT10M"
        }

+ Response 201

### deletes messages with specified tag [DELETE]

+ Request (text/plain)

        string value of the message text - only messages with the text (and specified tag) will be deleted

+ Parameters
  + tag (string) - tag

+ Response 204

### returns all messages with specified tag [GET]

+ Parameters
  + tag (string) - tag

+ Response 200 (application/json)

        [
          {
            "expired": false,
            "created": "2019-01-23 20:39:31 CET",
            "tags": [
              "main"
            ],
            "expiration": "2019-01-23 20:49:31 CET",
            "cssClass": "class",
            "text": "test&nbsp;message"
          }
        ]

## Monitoring [/metrics/prometheus]

### retrieves web application metrics in Prometheus format [GET]

+ Response 200 (text/plain)

## Path descriptions [/system/pathdesc]

### updates path descriptions for web application [POST]

This will refresh the path descriptions. The web application will store
the descriptions in a file under data root so it is not necessary to load the path
descriptions manually after each web application redeploy.

The paths are relative to source root, starting with /.

+ Request (application/json)
  + Body

            [
                {"path": "/foo", "description": "foo foo"},
                {"path": "/bar", "description": "bar"}
            ]


+ Response 204

## Web app version [/system/version]

### get web app version as string [GET]

+ Request (text/plain)
  + Body

            1.9.0 (a5ac05426bc5029158fedffee1cd44abf033bb61)

+ Response 200

## Ping the webapp [/system/ping]

This endpoint is used by the indexer when running with the -U option.

### Check if web app is deployed and alive [GET]

+ Response 200

## Groups [/groups]

### returns a list of all groups [GET]

+ Response 200 (application/json)
  + Body

            ["foo","bar"]

## Projects of a group [/groups/{group}/allprojects]

### returns list of all projects for given group [GET]

This includes also projects of any sub-groups.

+ Response 200 (application/json)
  + Body

            ["foo","bar"]

## Group pattern [/groups/{group}/pattern]

### returns pattern for given group [GET]

+ Response 200 (text/plain)
  + Body

            ^foo-.*

## Group match [/groups/{group}/match]

### check if (project) name matches group pattern [POST]

+ Request (text/plain)
  + Body

            name of the project

+ Response 200
+ Response 204

## Projects [/projects]

### returns a list of all projects [GET]

+ Response 200 (application/json)
  + Body

            ["foo","bar"]

### add project [POST]

This will merely add the project and its repositories to the web application configuration.
The project will not be searchable (and thus appear in the UI) until it is indexed.
If the project is already present in the configuration, the list of its repositories will be refreshed
if history is enabled.

+ Request (text/plain)
  + Body
  
            text/plain name of the project

+ Response 201

## Project management [/projects/{project}]

### delete project [DELETE]

This will remove the project and its repositories from the web application configuration.
It will also delete project specific data such as index, cross reference pages, history index
and suggester data.

+ Response 204

## Project data management [/projects/{project}/data]

### delete project index data [DELETE]

This will delete project index data but keep the project in web application configuration so that
can be indexed from scratch.
The project data (whatever is the project's directory under source root) will be left intact.
This will also mark the project as not indexed.

+ Response 204

## Project history cache management [/projects/{project}/historycache]

### delete history cache for a project [DELETE]

This will delete history cache for a project.
Return list of repository paths for which the cache was successfully deleted.

+ Response 200 (application/json)
  + Body

            ["/project/repository1","/project/repository2"]

## Project annotation cache management [/projects/{project}/annotationcache]

### delete annotation cache for a project [DELETE]

This will delete annotation cache for a project.
Return list of repository paths for which the cache was successfully deleted.

+ Response 200 (application/json)
  + Body

            ["/project/repository1","/project/repository2"]

## Project metadata management [/projects/{project}/indexed]

This entry point is used by the Indexer once it finishes indexing given project.

### marks project as indexed [PUT]

This is asynchronous API endpoint.

+ Request (text/plain)
  + Body

            empty

+ Response 204

## Project index files [/projects/{project}/files]

### Get a list of files tracked by the index database for given project [GET]

+ Response 200 (application/json)
  + Body

            ["/project/foo.txt","/project/bar.txt"]

## Project metadata [/projects/{project}/property/{propertyname}]

The list of per project properties can be found on
https://github.com/oracle/opengrok/wiki/Per-project-configuration#properties

### sets property value for the project [PUT]

+ Request
  + Body

            body – string representation of the value to set

+ Response 204

### returns the property value [GET]

+ Response 200 (application/json)

## Project repositories [/projects/{project}/repositories]

### returns a list of repositories for the specified project [GET]

Native path separators (of the system running the service)
will be used for repository paths.

+ Response 200 (application/json)
  + Body

            ["/opengrok-master/testdata/repositories/teamware",
             "/opengrok-master/testdata/sources/rfe2575",
             "/opengrok-master/testdata/repositories/rcs_test",
             "/opengrok-master"]

## Repository type [/projects/{project}/repositories/type]

### returns types of project repositories [GET]

+ Response 200 (application/json)
  + Body

            ["RCS","git","SCCS"]

## Project indexed flag [/projects/indexed]

### returns a list of indexed projects [GET]

+ Response 200 (application/json)
  + Body

            ["sc-2","sc-1"]

## Repository field value [/repositories/property/{field}{?repository}]

### return the field value [GET]

The repository path is relative to source root. Examples of field names:
  - `working` (boolean) - is the repository capable of running underlying SCM
    commands
  - `type` (string) - type of SCM
  - `remote` (boolean) - is the SCM source remote
  - `parent` (string) - origin/parent of the SCM
  - `branch` (string) - branch identification
  - `currentVersion` (string) - current revision ID
  - `handleRenamedFiles` (boolean) - whether to handle renamed files for history
    cache generation
  - `historyEnabled` (boolean) - is history enabled
  - `annotationCacheEnabled` (boolean) - is annotation cache enabled

The repository path is relative to source root.

+ Response 200 (application/json)

+ Parameters
  + repository - repository path with native path separators (of the machine
  running the service) starting with path separator for which to return type

## Search [/search{?full,def,symbol,path,hist,type,projects,maxresults,start}]

## return search results [GET]

+ Parameters
  + full (optional, string) - full search field value to search for
  + def (optional, string) - definition field value to search for
  + symbol (optional, string) - symbol field value to search for
  + path (optional, string) - file path field value to search for
  + hist (optional, string) - history field value to search for
  + type (optional, string) - type of the files to search for
  + projects (optional, string) - projects to search in
  + maxresults (optional, string) - maximum number of documents whose hits will be returned (default 1000)
  + start (optional, string) - start index from which to return results

+ Response 200 (application/json)
  + Body
  
            {
              "time": 1229,
              "resultCount": 8,
              "startDocument": 0,
              "endDocument": 7,
              "results": {
                "/onnv/usr/src/lib/libnisdb/db_pickle.cc": [
                  {
                    "line": "pickle_file::<b>transfer</b>(pptr p, bool_t (*f) (XDR*, pptr))",
                    "lineNumber": "106",
                    "tag": "function in pickle_file"
                  }
                ],
                "/onnv/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Resource.java": [
                  {
                    "line": "\tpublic void <b>transfer</b>(Resource donor, long qty) throws PoolsException",
                    "lineNumber": "93",
                    "tag": "method in Resource"
                  },
                  {
                    "line": "\tpublic void <b>transfer</b>(Resource donor, List components)",
                    "lineNumber": "110",
                    "tag": "method in Resource"
                  }
                ],
              }
            }

## Suggester [/suggest{?projects,field,caret,full,defs,refs,path,hist,type}]

### returns suggestions [GET]

+ Parameters
  + projects (string) - list of projects for which to retrieve suggestions
  + field - field for which to suggest
  + caret - position of the caret in the input field
  + full - value of the Full Search input
  + defs - value of the Definitions input
  + refs - value of Symbol input
  + path - value of the File Path input
  + hist - value of the History input
  + type - value of the Type input

+ Response 200 (application/json)
  + Body
  
            {
              "time": 60,
              "suggestions": [{
                "phrase": "package",
                "projects": ["kotlin"],
                "score": 387
              }],
              "identifier": "pprttq",
              "queryText": "pprttq",
              "partialResult":false
            }

## Suggester configuration [/suggest/config]

### returns suggester configuration [GET]

+ Response 200 (application/json)
  + Body
  
            {"enabled":true,"maxResults":10,"minChars":4,"allowedProjects":null,
             "maxProjects":2147483647,
             "allowedFields":["defs","path","hist","refs","type","full"],
             "allowComplexQueries":true,"allowMostPopular":true,"showScores":false,
             "showProjects":true,"showTime":false,"rebuildCronConfig":"0 0 * * *",
             "buildTerminationTime":1800,"timeThreshold":2000}  

## Suggester popularity data initialization with queries [/suggest/init/queries]

### updates popularity data based on the queries [POST]

+ Request (application/json)
  + Body

            ["http://localhost:8080/source/search?project=kotlin&full=text"]

+ Response 204

## Suggester popularity data initialization [/suggest/init/raw]

### updates popularity data based on the provided data [POST]

+ Request (application/json)
  + Body

            [{"project":"kotlin","field":"full","token":"args","increment":100}]

+ Response 204

## Suggester popularity data [/suggest/popularity/{project}{?field,page,pageSize,all}]

### retrieves popularity data for project [GET]

+ Parameters
  + field - field for which to retrieve data, default: full
  + page - page of data, default: 0
  + pageSize - size of the page, default: 100
  + all - if all data should be retrieved, if true then page and pageSize params are ignored

+ Response 200 (application/json)
  + Body

            [{"iso":3},{"the":3},{"to":3},{"conform":3},{"-":2},
             {"sc_window_set":1},{"_lso_outbound":1},{"missing":1}]

## Suggester data rebuild [/suggest/rebuild]

### rebuilds suggester data for all projects [PUT]

This kicks off suggester data rebuild in the background, i.e. the rebuild will very likely complete some time after the API call returned.

+ Response 204

## Suggester project data rebuild [/suggest/rebuild/{project}]

### rebuilds suggester data for given project [PUT]

This kicks off suggester data rebuild in the background, i.e. the rebuild will very likely complete some time after the API call returned.

+ Parameters
  + project - project name

+ Response 204

## Status [/status/{uuid}]

### Check the state of API request [GET]

+ Parameters
  + uuid

+ Response 202

### Delete state associated with API request tracking [DELETE]

This should be done only after the API request is completed, i.e. after the GET request for the API request state
returns appropriate status code (e.g. 201).

+ Parameters
  + uuid

+ Response 200
